/*
 * Copyright (c) InContent.
 * Author: Val
 * Modified At: 16-3-15 下午2:22
 */

package org.alfalfa.datawarehouse;

import com.alibaba.fastjson.JSONObject;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.Filters;
import org.bson.Document;
import org.bson.types.Binary;
import org.bson.types.ObjectId;
import org.springframework.util.FileCopyUtils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;

/**
 * @Author : Val
 * @Created : 2015-10-12
 * @E-mail : valer@126.com
 * @Version : 1.0
 */
public class DWRecord {

	private MongoCollection<Document> collection;
	protected Document document;

	protected DWRecord(MongoCollection<Document> collection, Document document) {
		this.collection = collection;
		this.document = document;
	}

	public Document getDocument() {
		return document;
	}

	public ObjectId getObjectId() {
		return document.getObjectId("_id");
	}

	public DWRecord remove(String key) {
		document.remove(key);
		return this;
	}

	public DWRecord put(String key, Object value) {
		document.put(key, value);
		return this;
	}

	public Object get(String key) {
		return document.get(key);
	}

	public <T> T get(String key, Class<T> cls) {
		Object o = document.get(key);
		return (T) o;
	}

	public Integer getInteger(Object key) {
		return document.getInteger(key);
	}

	public int getInteger(Object key, int defaultValue) {
		return document.getInteger(key, defaultValue);
	}

	public Long getLong(Object key) {
		return document.getLong(key);
	}

	public Double getDouble(Object key) {
		return document.getDouble(key);
	}

	public String getString(Object key) {
		return document.getString(key);
	}

	public Boolean getBoolean(Object key) {
		return document.getBoolean(key);
	}

	public boolean getBoolean(Object key, boolean defaultValue) {
		return document.getBoolean(key, defaultValue);
	}

	public ObjectId getObjectId(Object key) {
		return document.getObjectId(key);
	}

	public Date getDate(Object key) {
		return document.getDate(key);
	}

	public DWRecord putStream(String key, InputStream is) {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		try {
			FileCopyUtils.copy(is, bos);
		} catch (IOException e) {
			e.printStackTrace();
		}

		document.put(key, bos.toByteArray());
		try {
			bos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return this;
	}

	public InputStream getStream(String key) {

		Object o = document.get(key);
//		if (o instanceof Byte[]) {
		if (o == null) return null;
		byte[] bytes = (byte[]) o;

		return new ByteArrayInputStream(bytes);
//		} else {
//			Binary binary = document.get(key, Binary.class);
//			if (binary == null) return null;
//			return new ByteArrayInputStream(binary.getData());
//		}

	}

	public DWRecord mergeAll(Document doc) {
		for (String key : doc.keySet()) {
			document.put(key, doc.get(key));
		}
		return this;
	}

	public JSONObject getAsJSON() {
		JSONObject json = new JSONObject();

		for (String key : document.keySet()) {
			Object o = document.get(key);
			if (o instanceof ObjectId) o = ((ObjectId) o).toHexString();
			if (o instanceof Binary) continue;

			json.put(key, o);
		}
		return json;
	}

	public void save() {
		if (getObjectId() == null) {
			//this object is new,just insert it!
			collection.insertOne(document);
			return;
		}

		collection.updateOne(Filters.eq("_id", document.getObjectId("_id")), new Document("$set", document));
	}

	public void destroy() {
		if (getObjectId() != null) {
			collection.deleteOne(Filters.eq("_id", getObjectId()));
		}
	}

}
